/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.ssau.entities;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedList;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.NoSuchEntityException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.jdom.Element;
import ru.ssau.lib.StringIntegerPair;
import ru.ssau.utils.XMLHelper;
import ru.ssau.utils.DatabaseUtil;


public class ThreadBean implements EntityBean {
    
    private static final String REQUEST_THREAD_ADD =
            "INSERT INTO Threads(ThreadID,Caption) VALUES(?,?)";
    private static final String REQUEST_THREAD_ID_SEQUENCE_GET_NEXT_VALUE =
            "SELECT ThreadIDSeq.NEXTVAL FROM dual";
    private static final String REQUEST_THREAD_UPDATE =
            "UPDATE Threads SET Caption=? WHERE ThreadID=?";
    private static final String REQUEST_THREAD_GET_BY_ID =
            "SELECT Caption FROM Threads WHERE ThreadId=?";
    private static final String REQUEST_THREAD_FIND_BY_ID =
            "SELECT ThreadID FROM Threads WHERE ThreadId=?";
    private static final String REQUEST_THREAD_DELETE_BY_ID =
            "DELETE FROM Threads WHERE ThreadID=?";
    private static final String REQUEST_THREADS_GET_ALL =
            "SELECT ThreadID FROM Threads";
    private static final String REQUEST_THREADS_FIND_BY_CAPTION =
            "SELECT ThreadID FROM Threads WHERE UPPER(Caption) LIKE UPPER(?)";
    private static final String REQUEST_THREADS_GET_ALL_AS_STRING_INTEGER_PAIRS =
            "SELECT ThreadID, Caption FROM Threads";
    
    private Integer id;
    private String caption;
    
    private EntityContext entityContext;
    private DataSource dataSource;

    private boolean isEdited;

    
    public void setEntityContext(EntityContext ctx) {
        entityContext = ctx;
        try {
            dataSource = DatabaseUtil.getDataSource();
            isEdited = false;
        } catch(NamingException ex) {
            throw new EJBException("Cannon lookup connection pool on server", ex);
        }
    }
    
    public void unsetEntityContext() {
        entityContext = null;
    }
    
    public Integer ejbCreate(String caption) throws CreateException {
        PreparedStatement idGeneratePS = null;
        PreparedStatement updatePS = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            //id generation
            idGeneratePS = conn.prepareStatement(REQUEST_THREAD_ID_SEQUENCE_GET_NEXT_VALUE);
            ResultSet rs = idGeneratePS.executeQuery();
            if(rs.next()) {
                id = rs.getInt(1);
            } else {
                throw new CreateException("Cannot generate id for thread");
            }
            //Выпилить?.. (за ненадобностью)
            /*try {
                ejbFindByPrimaryKey(id);
                throw new DuplicateKeyException("Duplicate primary key: " + id.toString());
            } catch(ObjectNotFoundException e) {}*/
            //database updating
            updatePS = conn.prepareStatement(REQUEST_THREAD_ADD);
            updatePS.setInt(1, id.intValue());
            updatePS.setString(2, caption);
            if(updatePS.executeUpdate() != 1) {
                throw new CreateException("Insertion error");
            }
            this.caption = caption;
            isEdited = false;
            return id;
        } catch(SQLException ex) {
            throw new EJBException("Error in INSERT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, idGeneratePS);
            DatabaseUtil.closeConnection(null, updatePS);
        }
    }
    
    public void ejbPostCreate(String caption) throws CreateException {
        
    }
    
    public Integer ejbFindByPrimaryKey(Integer primaryKey) throws ObjectNotFoundException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_THREAD_FIND_BY_ID);
            ps.setInt(1, primaryKey.intValue());
            ResultSet rs = ps.executeQuery();
            if(!rs.next()) {
                throw new ObjectNotFoundException("No entity found by id = " + primaryKey.toString());
            }
            return primaryKey;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public Collection<Integer> ejbFindByCaption(String caption) {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            LinkedList<Integer> keys = new LinkedList<Integer>();
            ps = conn.prepareStatement(REQUEST_THREADS_FIND_BY_CAPTION);

            ps.setString(1, DatabaseUtil.getContainsPattern(caption));
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                Integer key = Integer.valueOf(rs.getInt(1));
                keys.add(key);
            }
            return keys;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    /*
    public Collection<Integer> ejbFindAll() {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            LinkedList<Integer> keys = new LinkedList<Integer>();
            ps = conn.prepareStatement(requestThreadsGetAll);
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                Integer key = Integer.valueOf(rs.getInt(1));
                keys.add(key);
            }
            return keys;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }*/
    
    public void ejbActivate() {
        
    }
    
    public void ejbPassivate() {
        
    }
    
    public void ejbLoad() {
        PreparedStatement ps = null;
        Connection conn = null;
        id = (Integer) entityContext.getPrimaryKey();
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_THREAD_GET_BY_ID);
            ps.setInt(1, id);
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                caption = rs.getString("Caption");
            } else {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch (SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public void ejbStore() {
        if(!isEdited) return;
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_THREAD_UPDATE);
            ps.setString(1, caption);
            ps.setInt(2, id.intValue());
            if(ps.executeUpdate() < 1) {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in UPDATE statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public void ejbRemove() throws RemoveException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_THREAD_DELETE_BY_ID);
            ps.setInt(1, id.intValue());
            if(ps.executeUpdate() < 1) {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in DELETE statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public Collection<StringIntegerPair> ejbHomeGetAllAsStringIntegerPairs() {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_THREADS_GET_ALL_AS_STRING_INTEGER_PAIRS);
            ResultSet rs = ps.executeQuery();
            Collection<StringIntegerPair> pairs = new LinkedList<StringIntegerPair>();
            while(rs.next()) {
                Integer threadId = Integer.valueOf(rs.getInt("ThreadID"));
                String threadCaption = rs.getString("Caption");
                StringIntegerPair pair = new StringIntegerPair(threadId, threadCaption);
                pairs.add(pair);
            }
            return pairs;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public Integer getId() {
        return id;
    }

    public String getCaption() {
        return caption;
    }

    public void setCaption(String caption) {
        this.caption = caption;
        isEdited = true;
    }

    public String getStringRepresentation() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName());
        sb.append(": [id=");
        sb.append(id);
        sb.append(", caption=");
        sb.append(caption);
        sb.append("]");
        return sb.toString();
    }
    
    public Element toXMLElement() {
        Element root = new Element("Thread");
        XMLHelper.addElement(root, "id", id);
        XMLHelper.addElement(root, "caption", caption);
        return root;
    }

    public void loadFromXMLElement(Element data) {
        throw new UnsupportedOperationException();
    }
}

